﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Concurrent;

using PServiceBus.Services.Gateway.Runtime;
using PServiceBus.Core.Security;
using PServiceBus.Gateway.Interfaces;
using System.Text.RegularExpressions;

namespace PServiceBus.Services.Web {
    public partial class WebMessageBus : IDisposable {
        static readonly ConcurrentDictionary<string, WebMessageBus> _messageBuses = new ConcurrentDictionary<string, WebMessageBus>();
        private static Regex _topicPatternRegex = new Regex(@"(\*\.)|(\.\*)|(\*)", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnoreCase);

        static readonly Type _dictType = typeof(Dictionary<string, object>);
        static readonly string _typeIdentifier = "___type";
        static readonly string _classIdentifier = "___class";
        static readonly string _dictIdentifier = "dict";

        private bool _disposed;

        private WebMessageBus() { }


        public void Invoke(Action<WebMessageBus> action) {
            if (action == null) throw new ArgumentNullException("action");
            action(this);
        }

        public TReturn Get<TReturn>(Func<WebMessageBus, TReturn> func) {
            if (func == null) throw new ArgumentNullException("func");
            return func(this);
        }

        public Dictionary<string, string> Headers { private get; set; }

        public static WebMessageBus Select(string key, string username, string password, Dictionary<string, string> headers) {
            WebMessageBus bus;
            if (!_messageBuses.TryGetValue(key, out bus)) {
                _messageBuses.TryAdd(key, 
                    bus = new WebMessageBus() { 
                        ID = key,
                        Identity = new ESBIdentity(username, password),
                        Headers = headers
                });
            }
            return bus;
        }

        private IMessageBus _messageBus;
        internal IMessageBus MessageBus {
            get {
                if (_messageBus == null || (_messageBus != null && _messageBus.IsClosed)) 
                    _messageBus = GatewayMessageBus.Create(Configuration.ESBEndpointAddress, Identity, false, Headers);
                return _messageBus;
            }
        }

        public ESBIdentity Identity { get; set; }

        public string ID { get; set; }

        public bool IsConnected {
            get {
                return _messageBus != null && !_messageBus.IsClosed;
            }
        }

        #region IDisposable Members
        private void Dispose(bool disposing) {
            if (_disposed) return;

            if (disposing) 
                GC.SuppressFinalize(this);

            if (IsConnected)
                _messageBus.Dispose();

            WebMessageBus bus;
            _messageBuses.TryRemove(ID, out bus);

            _messageBus = null;
            _disposed = true;
        }

        ~WebMessageBus() {
            Dispose(false);
        }

        public void Dispose() {
            Dispose(true);
        }

        #endregion
    }
}
